/*
 * @desc 上传
 * */
define(['jquery', 'classer', 'plupload', 'tool', 'applications'], function($, classer, _1, tool, applications) {
    var uploader = {
        //创建上传对象
        build : function(options){
            var me = this, $el =  tool.get$el(options.el), temp;
            if($el.length == 1){
                var id = $el.attr('id') || me.getId();
                $el.attr('id', $el.attr('id') || id);
                options.id = options.browse_button = id;
                temp = me._build(options);
                return temp;
            }else if($el.length > 1){
                var arr = [];
                $el.each(function(){
                    var $el = $(this),
                        opts = $.extend({}, options, {el : this}),
                        id = $el.attr('id') || me.getId();
                    $el.attr('id', id);
                    opts.id = opts.browse_button = id;
                    temp = me._build(opts);
                    arr.push(temp);
                });
                return arr;
            }else if(!options.el && (options.browse_button || options.id)){
                var id = options.browse_button || options.id;
                options.id = options.browse_button = id;
            }
            return options;
        },

        _build : function(options){
            var type = options.type, myClass;
            if(type == 'thumbnail'){
                myClass = ThumbnailUploader;
            }else if(type == 'crop'){
                myClass = CropUploader;
            }else if(type == 'image'){
                myClass = ImageUploader;
            }else if(type == 'images'){
                myClass = ImagesUploader;
            }else{
                myClass = FileUploader;
            }
            //传递到服务端的参数
            options.multipart_params = $.extend(options.multipart_params, options.data, {type : type});
            return new myClass(options);
        },

        //获取ID
        getId : function(){
            return 'uploader_' + tool.rand(4);
        }

    };

    //上传类
    var Uploader = classer.extend({
        //创建上传对象
        init : function(options){
            options = $.extend({}, Uploader.defaults, options);
            if(options.baseUrl){
                options.flash_swf_url = options.baseUrl + '/' + options.flash_swf_url;
                options.silverlight_xap_url = options.baseUrl + '/' + options.silverlight_xap_url;
            }
            this.options = options;
            var up = new plupload.Uploader(options);
            this.addEvents(up, options);
            up.init();
        },

        //事件绑定
        addEvents : function(uploader, options){
            //已存在的文件列表
            var me = this,
                $container = options.queueContainer ? $(options.queueContainer) : $('#' + options.id).parent(),
                $files = $container.find('.files');
            this.$container = $container;
            if($files.length < 1) $files = $('<div class="files"></div>').appendTo($container);
            $files.before('<input name="' + options.idField + '" type="hidden" value="" />');
            this.$files = $files;

            //已存在的文件添加事件
            $files.find('.file').each(function () {
                $(this).find('.file-remove').click(function () {
                    $(this).closest('.file').remove();
                });
            });
            //文件列表
            this.addPreviewFiles(options.files);
            //远程数据
            if(options.fileUrl && options.fileIds){
                require(['ajaxer'], function(ajaxer){
                    ajaxer.ajax({
                        url : options.fileUrl,
                        data : {id : options.fileIds},
                        success : function(res){
                            var data = ajaxer.getPureData(res);
                            me.addPreviewFiles(data);
                        }
                    });
                });
            }

            //上传之前
            uploader.bind('BeforeUpload', function(up, file) {
                var maxNum = 10;
                if(up.files.length > maxNum) {
                    require(['dialoger'], function(dialoger){
                        dialoger.error({msg : '最多只能选择' + maxNum + '个文件！'});
                    });
                    up.stop();
                    return false;
                }
            });

            //添加文件
            uploader.bind('FilesAdded', function(up, files) {
                return me.added(up, files);
            });

            //开始上传
            if(options.upload_button){
                $(options.upload_button).click(function(){
                    uploader.start();
                    return false;
                });
            }

            //暂停上传
            if(options.stop_button) {
                $(options.stop_button).click(function () {
                    uploader.stop();
                    return false;
                });
            }

            //上传过程
            uploader.bind('UploadProgress', function(up, file) {
                return me.progress(up, file);
            });

            //上传完成
            uploader.bind('FileUploaded', function(up, file, info) {
                return me.uploaded(up, file, info);
            });

            uploader.bind("UploadComplete", function(up, files) {
                return me.complete(up, files);
            });

            //上传失败
            uploader.bind('Error', function(up, err) {
                return me.error(up, err);
            });
        },

        //添加已有文件
        addPreviewFiles : function(files){
            var me = this, options = this.options;
            if($.isArray(files) && files.length > 0){
                $.each(files, function(i, file){
                    var $file = $(
                        '<div class="file">' +
                            '<input name="' + options.idField + '" type="hidden" value="' + file.fileId + '" />' +
                            '<input name="' + options.pathField + '" type="hidden" value="' + file.path + '" />' +
                            '<input name="' + options.sizeField + '" type="hidden" value="' + file.size + '" />' +
                            '<div class="file-preview">' +
                                '<span class="file">' + file.source_name + '</span>' +
                                '<a class="file-remove" title="删除">×</a>' +
                            '</div>' +
                        '</div>');
                    //删除
                    $file.find('.file-remove').click(function(){
                        $(this).closest('.file').remove();
                    });
                    $file.appendTo(me.$files);
                });
            }
        },

        //添加文件
        added : function(up, files){
            var me = this, $files = this.$files,
                options = this.options, $file;
            for (var i in files) {
                $file = $(
                    '<div id="' + files[i].id + '" class="file">' +
                        '<input name="' + options.idField + '" type="hidden" value="" />' +
                        '<input name="' + options.pathField + '" type="hidden" value="" />' +
                        '<input name="' + options.sizeField + '" type="hidden" value="' + files[i].size + '" />' +
                        '<div class="file-view">' +
                            '<a class="file-remove" title="删除">×</a>' +
                            '<span class="file-name">' + files[i].name + '(' + plupload.formatSize(files[i].size) + ')</span>' +
                        '</div>' +
                        '<div class="file-progress" style="display:none">' +
                            '<div class="file-progress-bar" style="width:0%"></div>' +
                        '</div>' +
                    '</div>');
                //删除
                $file.find('.file-remove').click(function(){
                    up.removeFile($(this).closest('.file').attr('id'));
                    $(this).closest('.file').remove();
                });
                $files.append($file);
            }

            var addedCallback = options.addedCallback;
            if(typeof addedCallback == 'function'){
                addedCallback.apply(me, arguments);
            }

            if(options.autoUpload) up.start();
            return true;
        },

        //传输过程
        progress : function(up, file){
            var me = this, $file = $('#' + file.id),
                options = this.options,
                percent = file.percent + '%';
            $file.find('.file-progress').show();
            $file.find('.file-progress-bar').css({width : percent}).text(percent);
            var progressCallback = options.progressCallback;
            if(typeof progressCallback == 'function'){
                progressCallback.apply(me, arguments);
            }
            return true;
        },

        //单个文件上传完成
        uploaded : function(up, file, info){
            var me = this, response = {},
                options = this.options;
            if(/^\{.+\}$/.test(info.response)){
                response = $.parseJSON(info.response);
                if(!response.status) {
                    this.showError({msg : response.msg});
                    return false;
                }
            }else{
                this.showError({msg : '上传失败'});
                return false;
            }
            var $file = $('#' + file.id), percent = file.percent + '%';
            $file.find('.file-progress-bar').text(percent);
            
            //隐藏域值
            if(options.idField) $file.find('[name=' + options.idField + ']').val(response.data.fileId);
            if(options.pathField) $file.find('[name=' + options.pathField + ']').val(response.data.path);
            if(options.sizeField) $file.find('[name=' + options.sizeField + ']').val(file.size);

            //是否是单文件
            if(options.single && options.multi_selection == false){
                $file.siblings().remove();
            }

            this.hideProgressbar(file);

            //上传完成之后回调
            var callback = options.callback;
            if(typeof callback == 'function'){
                callback.apply(me, arguments);
            }
            return true;
        },

        //所有文件上传完成
        complete : function(up, files){
            var me = this, options = this.options;
            for (var i in files) {
                this.hideProgressbar(files[i]);
            }
            //所有上传完成之后回调
            var completeCallback = options.completeCallback;
            if(typeof completeCallback == 'function'){
                completeCallback.apply(me, arguments);
            }
            return true;
        },

        //上传失败
        error : function(up, err){
            var me = this, options = this.options;
            this.showError({msg : '上传失败:' + err.message});
            //所有失败回调
            var errorCallback = options.errorCallback;
            if(typeof errorCallback == 'function'){
                errorCallback.apply(me, arguments);
            }
        },

        //隐藏上传条
        hideProgressbar : function(file){
            var $file = $('#' + file['id']);
            $file.find('.file-progress').hide();
        },

        //显示错误
        showError : function(options){
            require(['dialoger'], function(dialoger){
                dialoger.error(options);
            });
        }

    }),

    //一般文件上传
    FileUploader = Uploader.extend({

    }),

    //图片上传
    ImageUploader = Uploader.extend({
        //创建上传对象
        init : function(options){
            options = $.extend(options, {
                filters : {
                    mime_types : [
                        {title : "Image files", extensions : "jpg,jpeg,bmp,gif,png"}
                    ]
                }
            });
            this._super.apply(this, [options]);
        },

        //单个文件上传完成
        uploaded : function(up, file, info){
            var b = this._super.apply(this, arguments);
            if(b){
                this.present(up, file, info);
                return true;
            }
        },

        //展示已上传的图片
        present : function(up, file, info){
            var options = this.options,
                $file = $('#' + file.id), $img,
                response = $.parseJSON(info.response);
            $img = $(
                '<div class="file-preview">' +
                    '<span class="image"><img src="' + response.data.address + '" /></span>' +
                    '<a class="file-remove" title="删除">×</a>' +
                    '<span class="file">' + response.data.source_name + '</span>' +
                '</div>');
            //删除
            $img.find('.file-remove').click(function(){
                $(this).closest('.file').remove();
            });
            $file.find('.file-view').hide();
            $file.append($img);
        },

        //添加已有文件
        addPreviewFiles : function(files){
            var me = this, options = this.options;
            if($.isArray(files) && files.length > 0){
                $.each(files, function(i, file){
                    var $file = $(
                        '<div class="file">' +
                            '<input name="' + options.idField + '" type="hidden" value="' + file.fileId + '" />' +
                            '<input name="' + options.pathField + '" type="hidden" value="' + file.path + '" />' +
                            '<input name="' + options.sizeField + '" type="hidden" value="' + file.size + '" />' +
                            '<div class="file-preview">' +
                                '<span class="image"><img src="' + file.address + '" /></span>' +
                                '<a class="file-remove" title="删除">×</a>' +
                                '<span class="file">' + file.source_name + '</span>' +
                            '</div>' +
                        '</div>');
                    //删除
                    $file.find('.file-remove').click(function(){
                        $(this).closest('.file').remove();
                    });
                    $file.appendTo(me.$files);
                });
            }
        }

    }),

    //缩略图上传
    ThumbnailUploader = ImageUploader.extend({

    }),

    //剪切图上传
    CropUploader = ImageUploader.extend({
        //展示已上传的图片
        present : function(up, file, info){
            var options = this.options,
                $file = $('#' + file.id), $img,
                response = $.parseJSON(info.response);
            $img = $(
                '<div class="over-hidden">' +
                    '<img src="' + response.data.address + '" />' +
                    '<div class="over-hidden" style="padding-top:5px;"><button class="btn btn-default save" type="button">保存</button></div>' +
                    '<div class="file-preview">' +
                        '<a class="file-remove" title="删除">×</a>' +
                        '<span class="file">' + response.data.source_name + '</span>' +
                    '</div>'+
                +'</div>');

            //保存
            $img.find('.save').click(function(){
                me.croper.save();
            });

            //删除
            $img.find('.file-remove').click(function(){
                $(this).closest('.file').remove();
            });
            $file.find('.file-view').hide();
            $file.append($img);

            var me = this, croperOptions = options.croper || {};
            require(['croper'], function(croper){
                me.croper = croper.build($.extend(croperOptions, 
                    {
                        url : options.cropurl
                    }, {
                    el : $file.find('img'),
                    success : function(){
                        me.cropSuccess.apply(me, arguments);
                    },
                    error : function(){
                        me.cropError.apply(me, arguments);
                    },
                    postData : {
                        fileId : response.data.fileId,
                    }
                }));
            });
        },

        //保存成功
        cropSuccess : function(data, textStatus, jqXHR){
            require(['dialoger'], function(dialoger){
                data = data || {};
                if(!data.status) dialoger.error({msg : data.msg || '保存失败'});
                else{
                    dialoger.success({msg : data.msg || '保存成功'});
                }
            });
        },

        //保存失败
        cropError : function(XMLHttpRequest, textStatus, errorThrown){
            require(['dialoger'], function(dialoger){
                dialoger.error({msg : '保存失败'});
            });
        }
    }),

    //多图上传
    ImagesUploader = ImageUploader.extend({
        //创建上传对象
        init : function(options){
            options = $.extend(options, {multi_selection : true, single : false});
            this._super.apply(this, [options]);
        }
    });

    //默认配置
    Uploader.defaults = {
        //上传类型，值：file/thumbnail/image/images/crop/flash/media,默认：file
        type : 'file',
        //触发浏览文件按钮标签的唯一id,,在flash、html5、和silverlight中能找到触发事件的源,※※※※必须※※※※
        browse_button : 'pickfiles',
        //上传服务器地址,※※※※必须※※※※
        url : applications.UPLOADURL,
        //剪切地址
        cropurl : applications.CROPURL,
        //获取已存在文件地址
        fileUrl : applications.FILEURL,
        //文件id
        fileIds : '',
        //已经存在的文件数组[{fileId : '', path : '', size : '', source_name : '', address : ''}]
        files : [],
        //是否只保存单个文件
        single : true,
        //关联文件ID的外键名称
        idField : 'fileId',
        //路径字段
        pathField : 'path',
        //文件大小字段
        sizeField : 'size',
        //上传文件键名
        file_data_name : 'file',
        //插件目录
        baseUrl : applications.BASEURL,
        //flash文件地址
        flash_swf_url : 'plupload/2.1.9/js/Moxie.swf',
        //silverlight所在路径
        silverlight_xap_url : 'plupload/2.1.9/js/Moxie.xap',
        //上传插件初始化选用那种方式的优先级顺序，如果第一个初始化失败就走第二个，依次类推
        runtimes : 'html5,silverlight,flash,html4,gears,browserplus',
        //上传按钮选择器
        upload_button : '',
        //暂停按钮选择器
        stop_button : '',
        //展现上传文件列表的容器选择器，默认上传按钮父元素
        queueContainer : '',
        //是否选择文件后自动上传
        autoUpload : true,
        //当上传文件大于服务器接收端文件大小限制的时候，可以分多次请求发给服务器，如果不需要从设置中移出
        chunk_size : '2mb',
        //当出现http错误时重试次数
        max_retries : 3,
        //上传的文件名是否唯一
        unique_names : true,
        //布尔值 如果是flash上传应该用URLStream 代替FileReference.upload
        urlstream_upload : true,
        //修改图片属性如：{width : 320, height : 240, quality : 90}，quality->品质
        resize : null,
        //选择文件扩展名的过滤器,每个过滤规则中只有title和ext两项[{title:'Image files', extensions:'jpg,gif,png'}]
        filters : {
            //最大上传文件大小（格式100b, 10kb, 10mb, 1gb）
            max_file_size : '2gb',
            //文件类型
            mime_types : [
                {title : "Image files", extensions : "jpg,jpeg,bmp,gif,png"},
                {title : "Zip files", extensions : "zip,rar,gz"},
                {title : "video files", extensions : "rmvb,flv,swf,rmvb,mp4,mp3"}
            ]
        },
        preinit : {
            UploadFile: function(up, file) {
                up.settings.multipart_params = $.extend(up.settings.multipart_params, {source_name : file.name});
            }
        },
        //检测是否已上传的input元素的id
        input : '',
        //布尔值，如果用mutlipart 代替二进制流的方式，在webkit下无法工作
        multipart : true,
        //是否支持拖拽，默认值true
        dragdrop : true,
        //是否可以多次上传
        multiple_queues : false,
        //是否可以选中多个
        multi_selection : false,
        //跟 multipart关联在一起的键值对
        multipart_params : {},
        //事件集合,例:{FileUploaded : function(up, file, res){}}
        init : {},
        //上传完成之后回调函数
        callback : null,
        //所有文件上传完成之后回调函数
        completeCallback : null,
        //上传失败回调函数
        errorCallback : null
    };

    return uploader;
});

/*
API文档：

方法列表：

　　Uploader(setting)：创建实例的构造方法

var uploader = new plupload.Uploader({
    runtimes : 'gears,html5,flash',
    browse_button : 'button_id'
});
　　bind(event, function[, scope])：绑定事件

uploader.bind('Init', function(up) {
    alert('Supports drag/drop: ' + (!!up.features.dragdrop));
});
　　destroy()：销毁plupload的实例对象

uploader.destroy()
　　getFile(id): 获取上传文件信息

uploader.bind('FilesAdded', function(up, files) {
    for (var i in files) {
        up.getFile(files[i].id);
    }
});<span style="color: #ff0000; font-size: 13px;">　</span>
注：file：{
　　id:文件编号,
　　loaded: 已经上传多少字节,
　　name: 文件名,
　　percent: 上传进度,
　　size: 文件大小,
　　status: 有四种状态 QUEUED, UPLOADING, FAILED, DONE.对应数值
}

init:初始化plupload实例，添加监听对象

uploader.destroy()
　　refresh：重新实例化uploader

　removeFile(id):从file中移除某个文件

　　splice(start,length)：从队列中start开始删除length个文件， 返回被删除的文件列表

　　start() 开始上传

stop()停止上传

　　unbind(name, function): 接触事件绑定

　　unbindAll()解绑所有事件

　属性集合：

features：uploader中包含那些特性

files:当前队列中的文件列表

id：uploader实例的唯一id

runtime：当前运行环境（是html5、flash等等)

state:当前上传进度状态

total：当前上传文件的信息集合

事件集合:（up为uploader缩写）

BeforeUpload(up, file)：文件上传完之前触发的事件

ChunkUploaded(up, file,response)文件被分块上传的事件

Destroy(up):uploader的destroy调用的方法

Error(up, err)：上传出错的时候触发

Fileadded(up, files):用户选择文件时触发

FileRemoved(up, files):当文件从上传队列中移除触发

FileUploaded(up, file, res):文件上传成功的时候触发

Init(up):当初始化的时候触发

PostInit(up):init执行完以后要执行的事件触发

QueueChanged(up):当文件队列变化时触发

Refresh(up):当silverlight/flash或是其他运行环境需要移动的时候触发

StateChanged(up)当整个上传队列被改变的时候触发

UploadComplete(up,file)当队列中所有文件被上传完时触发

UploadFile(up,file)当一个文件被上传的时候触发

UploadProgress(up,file):当文件正在被上传中触发

*/